package com.lantosec.hmrp.core.util;

import lombok.extern.log4j.Log4j2;
import org.apache.batik.transcoder.TranscoderInput;
import org.apache.batik.transcoder.TranscoderOutput;
import org.apache.batik.transcoder.image.PNGTranscoder;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.collections.CollectionUtils;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.bpmn.model.FlowElement;
import org.flowable.bpmn.model.SequenceFlow;
import org.flowable.bpmn.model.StartEvent;
import org.flowable.common.engine.api.FlowableException;
import org.flowable.common.engine.impl.de.odysseus.el.ExpressionFactoryImpl;
import org.flowable.common.engine.impl.de.odysseus.el.util.SimpleContext;
import org.flowable.common.engine.impl.javax.el.ExpressionFactory;
import org.flowable.common.engine.impl.javax.el.ValueExpression;
import org.flowable.engine.ProcessEngine;
import org.flowable.engine.ProcessEngines;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;

@Log4j2
public class FlowableUtils {
    public static ProcessEngine getEngine() {
        return ProcessEngines.getDefaultProcessEngine();
    }

    public static byte[] svg2Png(String svg) {
        try {
            InputStream svgStream = new ByteArrayInputStream(svg.getBytes(StandardCharsets.UTF_8));
            TranscoderInput input = new TranscoderInput(svgStream);
            PNGTranscoder transcoder = new PNGTranscoder();
            // Setup output
            ByteArrayOutputStream outStream = new ByteArrayOutputStream();
            TranscoderOutput output = new TranscoderOutput(outStream);
            // Do the transformation
            transcoder.transcode(input, output);
            final byte[] result = outStream.toByteArray();
            outStream.close();
            return result;
        } catch (Exception e) {
            log.error("SVG转PNG图片时出错.", e);
            throw new FlowableException("SVG转PNG图片时出错.", e);
        }
    }

     public static String svg2Base64(String svg) {
        try {
            byte[] result = svg2Png(svg);
            return Base64.encodeBase64String(result);
        } catch (Exception e) {
            log.error("SVG转Base64时出错.", e);
            throw new FlowableException("SVG转Base64时出错.", e);
        }
    }

    /**
     * 根据key和value判断el表达式是否通过信息
     *
     * @param el           el表达式信息
     * @param conditionMap el表达式传入值信息
     * @return
     */
    public static boolean isCondition(String el, Map<String, Object> conditionMap) {
        ExpressionFactory factory = new ExpressionFactoryImpl();
        SimpleContext context = new SimpleContext();
        for (String key : conditionMap.keySet()) {
            if (Objects.isNull(conditionMap.get(key))) {
                context.setVariable(key, factory.createValueExpression(conditionMap.get(key), String.class));
            } else {
                context.setVariable(key, factory.createValueExpression(conditionMap.get(key), conditionMap.get(key).getClass()));
            }
        }
        ValueExpression e = factory.createValueExpression(context, el, boolean.class);
        return (Boolean) e.getValue(context);
    }

    /**
     * 获取第一个用户任务节点的Id
     * @return
     */
    public static String getFirstUserTaskId(BpmnModel bpmnModel) {
        // 没有流程实例则默认第一个用户节点
        Collection<FlowElement> flowElements = bpmnModel.getMainProcess().getFlowElements();
        for (FlowElement flowElement : flowElements) {
            if (!Objects.isNull(flowElement) && flowElement instanceof StartEvent) {
                // 开始节点的出口就是第一个用户节点
                List<SequenceFlow> sequenceFlowList = ((StartEvent) flowElement).getOutgoingFlows();
                if (CollectionUtils.isNotEmpty(sequenceFlowList)) {
                    return sequenceFlowList.get(0).getTargetRef();
                }
            }
        }

        return null;
    }
}
